home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / emacssrc.zip / EMACSSRC.TAR / emacs-19.17 / src / ntproc.c < prev    next >
C/C++ Source or Header  |  1993-11-20  |  21KB  |  784 lines

  1. /*
  2.    Process support for Windows NT (tm) port of GNU EMACS.
  3.    Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Emacs.
  6.  
  7.    GNU Emacs is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by the
  9.    Free Software Foundation; either version 1, or (at your option) any later
  10.    version.
  11.  
  12.    GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14.    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15.    more details.
  16.  
  17.    You should have received a copy of the GNU General Public License along
  18.    with GNU Emacs; see the file COPYING.  If not, write to the Free Software
  19.    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.    Drew Bliss                   Oct 14, 1993
  22.      Adapted from alarm.c by Tim Fleehart
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <errno.h>
  28. #include <io.h>
  29. #include <signal.h>
  30.  
  31. #include "config.h"
  32.  
  33. #include <windows.h>
  34.  
  35. #include "lisp.h"
  36. #include "ntsig.h"
  37. #include "ntproc_p.h"
  38. #include "sysfdset.h"
  39. #include "systime.h"
  40. #include "process_p.h"
  41. #include "sysdep_p.h"
  42.  
  43. /* #define FULL_DEBUG */
  44.  
  45. /* Defined in process.h which conflicts with the local copy */
  46. #define    _P_NOWAIT 1
  47.  
  48. typedef struct _ChildProcess
  49. {
  50.     int fd;
  51.     HANDLE char_avail;
  52.     HANDLE char_consumed;
  53.     char chr;
  54.     BOOL status;
  55.     HANDLE process;
  56.     DWORD pid;
  57.     HANDLE thrd;
  58. } ChildProcess;
  59.  
  60. #define MAX_CHILDREN MAXDESC
  61.  
  62. #ifdef EMACSDEBUG
  63. void _CRTAPI1 _DebPrint(char *fmt, ...)
  64. {
  65.     char buf[256];
  66.     va_list args;
  67.  
  68.     va_start(args, fmt);
  69.     vsprintf(buf, fmt, args);
  70.     va_end(args);
  71.     OutputDebugString(buf);
  72. }
  73. #endif
  74.  
  75. /*
  76.    Child process management list
  77.    */
  78. static int child_proc_count = 0;
  79. static ChildProcess child_procs[MAX_CHILDREN];
  80. #define CHILD_ACTIVE(cp) ((cp)->process != NULL)
  81. #define DEACTIVATE_CHILD(cp) ((cp)->process = NULL)
  82.  
  83. static ChildProcess *dead_child = NULL;
  84.  
  85. /*
  86.    Signal handlers
  87.    SIG_DFL == 0 so this is initialized correctly
  88.    */
  89. static SignalHandler sig_handlers[NSIG];
  90.  
  91. /*
  92.    Fake signal implementation to record the SIGCHLD handler
  93.    */
  94. SignalHandler Signal(int sig, SignalHandler handler)
  95. {
  96.     SignalHandler old;
  97.     
  98.     if (sig != SIGCHLD)
  99.     {
  100.         errno = EINVAL;
  101.         return SIG_ERR;
  102.     }
  103.     old = sig_handlers[sig];
  104.     sig_handlers[sig] = handler;
  105.     return old;
  106. }
  107.  
  108. /*
  109.    Find an unused process slot
  110.    */
  111. static ChildProcess *NewChild(void)
  112. {
  113.     ChildProcess *cp;
  114.  
  115.     if (child_proc_count == MAX_CHILDREN)
  116.         return NULL;
  117.     
  118.     for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
  119.         if (!CHILD_ACTIVE(cp))
  120.             return cp;
  121.     return &child_procs[child_proc_count++];
  122. }
  123.  
  124. /*
  125.    Find a child by pid
  126.    */
  127. static ChildProcess *FindChildPid(DWORD pid)
  128. {
  129.     ChildProcess *cp;
  130.  
  131.     for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
  132.         if (CHILD_ACTIVE(cp) && pid == cp->pid)
  133.             return cp;
  134.     return NULL;
  135. }
  136.  
  137. /*
  138.    Find a child by fd
  139.    */
  140. static ChildProcess *FindChildFd(int fd)
  141. {
  142.     ChildProcess *cp;
  143.  
  144.     for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
  145.         if (CHILD_ACTIVE(cp) && fd == cp->fd)
  146.             return cp;
  147.     return NULL;
  148. }
  149.  
  150. /*
  151.    Thread proc for child process reader threads
  152.    The threads just sit in a loop waiting for input
  153.    When they detect input, they signal the char_avail input to
  154.    wake up the select emulator
  155.    When the select emulator processes their input, it pulses
  156.    char_consumed so that the reader thread goes back to reading
  157.    */
  158. DWORD WINAPI ReaderThread(void *arg)
  159. {
  160.     ChildProcess *cp;
  161.  
  162.     /* Our identity */
  163.     cp = (ChildProcess *)arg;
  164.  
  165.     /* We have to wait for the go-ahead before we can start */
  166.     if (WaitForSingleObject(cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
  167.         return 0;
  168.     /* If something went wrong, quit */
  169.     if (!cp->status)
  170.         return 0;
  171.     
  172.     for (;;)
  173.     {
  174.         /* Use read to get CRLF translation */
  175.         if (read(cp->fd, &cp->chr, sizeof(char)) == sizeof(char))
  176.         {
  177.             cp->status = TRUE;
  178.         }
  179.         else
  180.         {
  181. #ifdef FULL_DEBUG
  182.             DebPrint(("ReaderThread.read failed with %lu for fd %ld\n",
  183.                       GetLastError(), cp->fd));
  184. #endif
  185.             cp->status = FALSE;
  186.         }
  187.         
  188.         if (!SetEvent(cp->char_avail))
  189.         {
  190.             DebPrint(("ReaderThread.SetEvent failed with %lu for fd %ld\n",
  191.                       GetLastError(), cp->fd));
  192.             break;
  193.         }
  194.         
  195.         /* If the read died, the child has died so let the thread die */
  196.         if (!cp->status)
  197.             break;
  198.         
  199.         /* Wait until our input is acknowledged before reading again */
  200.         if (WaitForSingleObject(cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
  201.         {
  202.             DebPrint(("ReaderThread.WaitForSingleObject failed with "
  203.                       "%lu for fd %ld\n", GetLastError(), cp->fd));
  204.             break;
  205.         }
  206.     }
  207.     return 0;
  208. }
  209.  
  210. static BOOL CreateChild(char *exe, char *cmdline, char *env,
  211.                         PROCESS_INFORMATION *info)
  212. {
  213.     ChildProcess *cp;
  214.     DWORD id;
  215.     STARTUPINFO start;
  216.     SECURITY_ATTRIBUTES sec_attrs;
  217.     SECURITY_DESCRIPTOR sec_desc;
  218.  
  219.     cp = NewChild();
  220.     if (cp == NULL)
  221.         goto EH_Fail;
  222.  
  223.     cp->fd = -1;
  224.     
  225.     cp->char_avail = CreateEvent(NULL, FALSE, FALSE, NULL);
  226.     if (cp->char_avail == NULL)
  227.         goto EH_Fail;
  228.     
  229.     cp->char_consumed = CreateEvent(NULL, FALSE, FALSE, NULL);
  230.     if (cp->char_consumed == NULL)
  231.         goto EH_char_avail;
  232.     
  233.     cp->thrd = CreateThread(NULL, 1024, ReaderThread, cp, 0, &id);
  234.     if (cp->thrd == NULL)
  235.         goto EH_char_consumed;
  236.  
  237.     memset(&start, 0, sizeof(start));
  238.     start.cb = sizeof(start);
  239.  
  240.     /* Explicitly specify no security */
  241.     if (!InitializeSecurityDescriptor(&sec_desc, SECURITY_DESCRIPTOR_REVISION))
  242.         goto EH_thrd;
  243.     if (!SetSecurityDescriptorDacl(&sec_desc, TRUE, NULL, FALSE))
  244.         goto EH_thrd;
  245.     sec_attrs.nLength = sizeof(sec_attrs);
  246.     sec_attrs.lpSecurityDescriptor = &sec_desc;
  247.     sec_attrs.bInheritHandle = FALSE;
  248.     
  249.     if (!CreateProcess(exe, cmdline, &sec_attrs, NULL, TRUE,
  250.                        CREATE_NEW_PROCESS_GROUP, env, NULL,
  251.                        &start, info))
  252.         goto EH_thrd;
  253.     cp->process = info->hProcess;
  254.     cp->pid = info->dwProcessId;
  255.  
  256.     return TRUE;
  257.  
  258.  EH_thrd:
  259.     cp->status = FALSE;
  260.     SetEvent(cp->char_consumed);
  261.  EH_char_consumed:
  262.     CloseHandle(cp->char_consumed);
  263.  EH_char_avail:
  264.     CloseHandle(cp->char_avail);
  265.  EH_Fail:
  266.     return FALSE;
  267. }
  268.  
  269. /*
  270.    CreateChild doesn't know what emacs' file handle will be for waiting
  271.    on output from the child, so we need to make this additional call
  272.    to register the handle with the process
  273.    This way the select emulator knows how to match file handles with
  274.    entries in child_procs
  275.    */
  276. void RegisterChild(int pid, int fd)
  277. {
  278.     ChildProcess *cp;
  279.  
  280.     cp = FindChildPid(pid);
  281.     if (cp == NULL)
  282.     {
  283.         DebPrint(("RegisterChild unable to find pid %lu\n", pid));
  284.         return;
  285.     }
  286.  
  287. #ifdef FULL_DEBUG
  288.     DebPrint(("RegisterChild registered fd %d with pid %lu\n", fd, pid));
  289. #endif
  290.  
  291.     cp->fd = fd;
  292.     cp->status = TRUE;
  293.     /* Tell the reader thread to start */
  294.     if (!SetEvent(cp->char_consumed))
  295.     {
  296.         DebPrint(("RegisterChild.SetEvent failed with %lu for fd %ld\n",
  297.                   GetLastError(), cp->fd));
  298.     }
  299. }
  300.  
  301. /*
  302.    When a process dies its pipe will break so the reader thread will
  303.    signal failure to the select emulator.
  304.    The select emulator then calls this routine to clean up.
  305.    Since the thread signaled failure we can assume it is exiting
  306.    */
  307. static void RemoveChild(ChildProcess *cp)
  308. {
  309.     /* Reap the thread */
  310.     if (WaitForSingleObject(cp->thrd, INFINITE) != WAIT_OBJECT_0)
  311.     {
  312.         DebPrint(("RemoveChild.WaitForSingleObject(thread) failed "
  313.                   "with %lu for fd %ld\n", GetLastError(), cp->fd));
  314.     }
  315.     CloseHandle(cp->thrd);
  316.     CloseHandle(cp->char_consumed);
  317.     CloseHandle(cp->char_avail);
  318.  
  319.     /* Reap the process */
  320.     if (WaitForSingleObject(cp->process, INFINITE) != WAIT_OBJECT_0)
  321.     {
  322.         DebPrint(("RemoveChild.WaitForSingleObject(process) failed "
  323.                   "with %lu for fd %ld\n", GetLastError(), cp->fd));
  324.     }
  325.     CloseHandle(cp->process);
  326.  
  327.     DEACTIVATE_CHILD(cp);
  328. }
  329.  
  330. /*
  331.    Wait for any of our existing child processes to die
  332.    When it does, close its handle
  333.    Return the pid and fill in the status if non-NULL
  334.    */
  335. int Wait(int *status)
  336. {
  337.     DWORD active, retval;
  338.     int nh;
  339.     ChildProcess *cp, *cps[MAX_CHILDREN];
  340.     HANDLE wait_hnd[MAX_CHILDREN];
  341.  
  342.     nh = 0;
  343.     if (dead_child != NULL)
  344.     {
  345.     /* We want to wait for a specific child */
  346.     wait_hnd[nh] = dead_child->process;
  347.         cps[nh] = dead_child;
  348.         nh++;
  349.     }
  350.     else
  351.     {
  352.         for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
  353.             if (CHILD_ACTIVE(cp))
  354.             {
  355.                 wait_hnd[nh] = cp->process;
  356.                 cps[nh] = cp;
  357.                 nh++;
  358.             }
  359.     }
  360.  
  361.     if (nh == 0)
  362.     {
  363.         /* Nothing to wait on, so fail */
  364.         errno = ECHILD;
  365.         return -1;
  366.     }
  367.  
  368.     active = WaitForMultipleObjects(nh, wait_hnd, FALSE, INFINITE);
  369.     if (active == WAIT_FAILED)
  370.     {
  371.         errno = EBADF;
  372.         return -1;
  373.     }
  374.     else if (active == WAIT_TIMEOUT)
  375.     {
  376.         /* Should never happen */
  377.         errno = EINVAL;
  378.         return -1;
  379.     }
  380.     else if (active >= WAIT_OBJECT_0 &&
  381.              active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
  382.     {
  383.         active -= WAIT_OBJECT_0;
  384.     }
  385.     else if (active >= WAIT_ABANDONED_0 &&
  386.              active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
  387.     {
  388.         active -= WAIT_ABANDONED_0;
  389.     }
  390.     
  391.     if (!GetExitCodeProcess(wait_hnd[active], &retval))
  392.     {
  393.         DebPrint(("Wait.GetExitCodeProcess failed with %lu\n",
  394.                   GetLastError()));
  395.         retval = 1;
  396.     }
  397.     if (retval == STILL_ACTIVE)
  398.     {
  399.         /* Should never happen */
  400.         DebPrint(("Wait.WaitForMultipleObjects returned an active process\n"));
  401.         errno = EINVAL;
  402.         return -1;
  403.     }
  404.  
  405.     cp = cps[active];
  406. #ifdef FULL_DEBUG
  407.     DebPrint(("Wait signaled with process pid %d\n", cp->pid));
  408. #endif
  409.     
  410.     if (status)
  411.     {
  412.         /* In process.c the default WAITTYPE is defined.
  413.            Since we can't determine anything about why a process died
  414.            we can only return a code that looks like WIFEXITED */
  415.         *status = (retval & 0x7fffff) << 8;
  416.     }
  417.     
  418.     return cp->pid;
  419. }
  420.  
  421. /*
  422.    When a new child process is created we need to register it in our list,
  423.    so intercept spawn requests
  424.    */
  425. int Spawnve(int mode, char *cmdname, char **argv, char **envp)
  426. {
  427.     char *cmdline, *env, *parg, **targ;
  428.     int arglen;
  429.     PROCESS_INFORMATION pi;
  430.  
  431.     if (child_proc_count == MAX_CHILDREN)
  432.     {
  433.         errno = EAGAIN;
  434.         return -1;
  435.     }
  436.  
  437.     /* We don't care about the other modes */
  438.     if (mode != _P_NOWAIT)
  439.     {
  440.         errno = EINVAL;
  441.         return -1;
  442.     }
  443.  
  444.     /*
  445.      * we have to do some conjuring here to put argv and envp into the
  446.      * form CreateProcess wants...  argv needs to be a space separated/null
  447.      * terminated list of parameters, and envp is a null
  448.      * separated/double-null terminated list of parameters.
  449.      *
  450.      * Since I have no idea how large argv and envp are likely to be
  451.      * we figure out list lengths on the fly and allocate them.
  452.      */
  453.  
  454.     /*
  455.      * do argv...
  456.      */
  457.     arglen = 0;
  458.     targ = argv;
  459.     while (*targ)
  460.     {
  461.         arglen += strlen(*targ++) + 1;
  462.     }
  463.     cmdline = malloc(arglen);
  464.     if (cmdline == NULL)
  465.     {
  466.         errno = ENOMEM;
  467.         goto EH_Fail;
  468.     }
  469.     targ = argv;
  470.     parg = cmdline;
  471.     while (*targ)
  472.     {
  473.         strcpy(parg, *targ);
  474.         parg += strlen(*targ++);
  475.         *parg++ = ' ';
  476.     }
  477.     *--parg = '\0';
  478.  
  479.     /*
  480.      * and envp...
  481.      */
  482.     arglen = 1;
  483.     targ = envp;
  484.     while (*targ)
  485.     {
  486.         arglen += strlen(*targ++) + 1;
  487.     }
  488.     env = malloc(arglen);
  489.     if (env == NULL)
  490.     {
  491.         errno = ENOMEM;
  492.         goto EH_cmdline;
  493.     }
  494.     targ = envp;
  495.     parg = env;
  496.     while (*targ)
  497.     {
  498.         strcpy(parg, *targ);
  499.         parg += strlen(*targ++);
  500.         *parg++ = '\0';
  501.     }
  502.     *parg = '\0';
  503.  
  504.     /*
  505.      * Now create the process.
  506.      */
  507.     if (!CreateChild(cmdname, cmdline, env, &pi))
  508.     {
  509.         errno = ENOEXEC;
  510.         goto EH_env;
  511.     }
  512.     
  513.     return pi.dwProcessId;
  514.  
  515.  EH_env:
  516.     free(env);
  517.  EH_cmdline:
  518.     free(cmdline);
  519.  EH_Fail:
  520.     return -1;
  521. }
  522.  
  523. /*
  524.    Emulate the select call
  525.    Wait for available input on any of the given rfds, or timeout if
  526.    a timeout is given and no input is detected
  527.    wfds and efds are not supported and must be NULL
  528.    */
  529. /* From ntterm.c */
  530. extern HANDLE Keyboard;
  531. /* From process.c */
  532. extern int proc_buffered_char[];
  533.  
  534. int select(int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
  535.            EMACS_TIME *timeout)
  536. {
  537.     SELECT_TYPE orfds;
  538.     DWORD timeout_ms;
  539.     int i, nh, nr;
  540.     DWORD active;
  541.     ChildProcess *cp, *cps[MAX_CHILDREN];
  542.     HANDLE wait_hnd[MAX_CHILDREN];
  543.  
  544.     /* We only handle rfds, so fail otherwise */
  545.     if (rfds == NULL || wfds != NULL || efds != NULL)
  546.     {
  547.         errno = EINVAL;
  548.         return -1;
  549.     }
  550.  
  551.     orfds = *rfds;
  552.     FD_ZERO(rfds);
  553.     nr = 0;
  554.  
  555.     /*
  556.        Build a list of handles to wait on
  557.        */
  558.     nh = 0;
  559.  
  560.     for (i = 0; i < nfds; i++)
  561.         if (FD_ISSET(i, &orfds))
  562.         {
  563.             if (i == 0)
  564.             {
  565.                 /* Handle stdin specially */
  566.                 wait_hnd[nh] = Keyboard;
  567.                 cps[nh] = NULL;
  568.                 nh++;
  569.  
  570.                 /* Check for any emacs-generated input in the queue since
  571.                    it won't be detected in the wait */
  572.                 if (detect_input_pending())
  573.                 {
  574.                     FD_SET(i, rfds);
  575.                     nr++;
  576.                 }
  577.             }
  578.             else
  579.             {
  580.                 /* Child process input */
  581.  
  582.                 cp = FindChildFd(i);
  583.                 if (cp)
  584.                 {
  585. #ifdef FULL_DEBUG
  586.                     DebPrint(("select waiting on child %d fd %d\n",
  587.                               cp-child_procs, i));
  588. #endif
  589.                     wait_hnd[nh] = cp->char_avail;
  590.                     cps[nh] = cp;
  591.                     nh++;
  592.                 }
  593.                 else
  594.                 {
  595.                     /* Unable to find something to wait on for this fd, fail */
  596.                     DebPrint(("select unable to find child process "
  597.                               "for fd %ld\n", i));
  598.                     nh = 0;
  599.                     break;
  600.                 }
  601.             }
  602.         }
  603.         
  604.     /* Nothing to look for, so we didn't find anything */
  605.     if (nh == 0)
  606.         return 0;
  607.  
  608.     /* Check for immediate return without waiting */
  609.     if (nr > 0)
  610.         return nr;
  611.  
  612.     /*
  613.        Wait for input
  614.        If a child process dies while this is waiting, its pipe will break
  615.        so the reader thread will signal an error condition, thus, the wait
  616.        will wake up
  617.        */
  618.     timeout_ms = timeout ? *timeout*1000 : INFINITE;
  619.     active = WaitForMultipleObjects(nh, wait_hnd, FALSE, timeout_ms);
  620.     if (active == WAIT_FAILED)
  621.     {
  622.     DebPrint(("select.WaitForMultipleObjects(%d, %lu) failed with %lu\n",
  623.           nh, timeout_ms, GetLastError()));
  624.         /* Is there a better error? */
  625.         errno = EBADF;
  626.         return -1;
  627.     }
  628.     else if (active == WAIT_TIMEOUT)
  629.     {
  630.         return 0;
  631.     }
  632.     else if (active >= WAIT_OBJECT_0 &&
  633.              active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
  634.     {
  635.         active -= WAIT_OBJECT_0;
  636.     }
  637.     else if (active >= WAIT_ABANDONED_0 &&
  638.              active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
  639.     {
  640.         active -= WAIT_ABANDONED_0;
  641.     }
  642.  
  643.     if (cps[active] == NULL)
  644.     {
  645.         /* Keyboard input available */
  646.         FD_SET(0, rfds);
  647.         nr++;
  648.  
  649.         /* This shouldn't be necessary, but apparently just setting the input
  650.            fd is not good enough for emacs */
  651.         read_input_waiting();
  652.     }
  653.     else
  654.     {
  655.         /* Child process */
  656.         cp = cps[active];
  657.  
  658.         /* If status is FALSE the read failed so don't report input */
  659.         if (cp->status)
  660.         {
  661.             FD_SET(cp->fd, rfds);
  662.             proc_buffered_char[cp->fd] = cp->chr;
  663.             nr++;
  664.         }
  665.         else
  666.         {
  667.             /* The SIGCHLD handler will do a Wait so we know it won't
  668.                return until the process is dead
  669.            We force Wait to only wait for this process to avoid it
  670.            picking up other children that happen to be dead but that
  671.            we haven't noticed yet
  672.                SIG_DFL for SIGCHLD is ignore? */
  673.             if (sig_handlers[SIGCHLD] != SIG_DFL &&
  674.                 sig_handlers[SIGCHLD] != SIG_IGN)
  675.             {
  676. #ifdef FULL_DEBUG
  677.                 DebPrint(("select calling SIGCHLD handler for pid %d\n",
  678.                           cp->pid));
  679. #endif
  680.         dead_child = cp;
  681.                 sig_handlers[SIGCHLD](SIGCHLD);
  682.         dead_child = NULL;
  683.             }
  684.             
  685.             /* Clean up the child process entry in the table */
  686.             RemoveChild(cp);
  687.         }
  688.     }
  689.     return nr;
  690. }
  691.  
  692. /*
  693.    Substitute for certain kill() operations
  694.    */
  695. int Win32KillProcess(int pid, int sig)
  696. {
  697.     ChildProcess *cp;
  698.  
  699.     /* Only handle signals that will result in the process dying */
  700.     if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
  701.     {
  702.         errno = EINVAL;
  703.         return -1;
  704.     }
  705.  
  706.     cp = FindChildPid(pid);
  707.     if (cp == NULL)
  708.     {
  709.     DebPrint(("Win32KillProcess didn't find a child with pid %lu\n", pid));
  710.         errno = ECHILD;
  711.         return -1;
  712.     }
  713.  
  714.     if (sig == SIGINT)
  715.     {
  716.         /* Fake Ctrl-Break.  Ctrl-C doesn't seem to have any effect */
  717.         if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid))
  718.         {
  719.             DebPrint(("Win32KillProcess.GenerateConsoleCtrlEvent return %d "
  720.                       "for pid %lu\n", GetLastError(), pid));
  721.             errno = EINVAL;
  722.             return -1;
  723.         }
  724.     }
  725.     else
  726.     {
  727.         /* Kill the process.  On Win32 this doesn't kill child processes
  728.            so it doesn't work very well for shells which is why it's
  729.            not used in every case */
  730.         if (!TerminateProcess(cp->process, 0xff))
  731.         {
  732.             DebPrint(("Win32KillProcess.TerminateProcess returned %d "
  733.                       "for pid %lu\n", GetLastError(), pid));
  734.             errno = EINVAL;
  735.             return -1;
  736.         }
  737.     }
  738.     return 0;
  739. }
  740.  
  741. /*
  742.    If the channel is a pipe this read might block since we don't
  743.    know how many characters are available, so check and read only
  744.    what's there
  745.    We also need to wake up the reader thread once we've read our data
  746.    */
  747. int ReadChildOutput(int fd, char *buf, int max)
  748. {
  749.     HANDLE h;
  750.     int to_read, nchars;
  751.     DWORD waiting;
  752.     ChildProcess *cp;
  753.     
  754.     h = (HANDLE)_get_osfhandle(fd);
  755.     if (GetFileType(h) == FILE_TYPE_PIPE)
  756.     {
  757.         PeekNamedPipe(h, NULL, 0, NULL, &waiting, NULL);
  758.         to_read = min(waiting, (DWORD)max);
  759.     }
  760.     else
  761.         to_read = max;
  762.  
  763.     /* Use read to get CRLF translation */
  764.     nchars = read(fd, buf, to_read);
  765.  
  766.     if (GetFileType(h) == FILE_TYPE_PIPE)
  767.     {
  768.         /* Wake up the reader thread
  769.            for this process */
  770.         cp = FindChildFd(fd);
  771.         if (cp)
  772.         {
  773.             if (!SetEvent(cp->char_consumed))
  774.                 DebPrint(("ReadChildOutput.SetEvent failed with "
  775.                           "%lu for fd %ld\n", GetLastError(), fd));
  776.         }
  777.         else
  778.             DebPrint(("ReadChildOutput couldn't find a child with fd %d\n",
  779.                       fd));
  780.     }
  781.     
  782.     return nchars;
  783. }
  784.